package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DistanceUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.UUIdUtils;
import com.ruoyi.oa.domain.OaHoliday;
import com.ruoyi.oa.domain.OaHumanClockTemp;
import com.ruoyi.oa.domain.bo.*;
import com.ruoyi.oa.domain.vo.*;
import com.ruoyi.oa.mapper.OaHumanClockTempMapper;
import com.ruoyi.oa.service.IOaHolidayService;
import com.ruoyi.oa.service.IOaHumanClockCountService;
import com.ruoyi.oa.service.IOaMessageService;
import com.ruoyi.system.domain.Dto.ClockUserDto;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.workflow.utils.WeChatUtil;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.annotations.Param;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.OaHumanClock;
import com.ruoyi.oa.mapper.OaHumanClockMapper;
import com.ruoyi.oa.service.IOaHumanClockService;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 考勤规则Service业务层处理
 *
 * @author ruoyi
 * @date 2023-07-18
 */
@RequiredArgsConstructor
@Service
@EnableScheduling
public class OaHumanClockServiceImpl implements IOaHumanClockService {

    private final OaHumanClockMapper baseMapper;

    private final IOaHumanClockCountService iOaHumanClockCountService;


    private final OaHumanClockTempMapper oaHumanClockTempMapper;


    private final IOaHolidayService iOaHolidayService;


    private final ISysDeptService iSysDeptService;

    private final ISysUserService iSysUserService;


    private final IOaMessageService iOaMessageService;
    /**
     * 查询考勤规则
     */
    @Override
    public OaHumanClockVo queryById(String id){
        OaHumanClockVo oaHumanClockTemp = oaHumanClockTempMapper.selectVoById(id);
        if (ObjectUtil.isNotEmpty(oaHumanClockTemp)){
            return oaHumanClockTemp;
        }else {
            return baseMapper.selectVoById(id);
        }
    }

    /**
     * 查询考勤规则列表
     */
    @Override
    public TableDataInfo<OaHumanClockVo> queryPageList(OaHumanClockBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OaHumanClock> lqw = buildQueryWrapper(bo);
        Page<OaHumanClockVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询考勤规则列表
     */
    @Override
    public List<OaHumanClockVo> queryList(OaHumanClockBo bo) {
        LambdaQueryWrapper<OaHumanClock> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<OaHumanClock> getAll() {
        return baseMapper.selectList();
    }

    private LambdaQueryWrapper<OaHumanClock> buildQueryWrapper(OaHumanClockBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OaHumanClock> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getRuleName()), OaHumanClock::getRuleName, bo.getRuleName());
        lqw.eq(StringUtils.isNotBlank(bo.getClockTypeList()), OaHumanClock::getClockTypeList, bo.getClockTypeList());
        lqw.eq(StringUtils.isNotBlank(bo.getClockTimeList()), OaHumanClock::getClockTimeList, bo.getClockTimeList());
        lqw.eq(StringUtils.isNotBlank(bo.getMindDate()), OaHumanClock::getMindDate, bo.getMindDate());
        lqw.eq(StringUtils.isNotBlank(bo.getTimeLimit()), OaHumanClock::getTimeLimit, bo.getTimeLimit());
        lqw.eq(StringUtils.isNotBlank(bo.getReplaceNumberPermon()), OaHumanClock::getReplaceNumberPermon, bo.getReplaceNumberPermon());
        lqw.eq(StringUtils.isNotBlank(bo.getDeadlinePermon()), OaHumanClock::getDeadlinePermon, bo.getDeadlinePermon());
        lqw.eq(StringUtils.isNotBlank(bo.getReplaceMind()), OaHumanClock::getReplaceMind, bo.getReplaceMind());
        lqw.eq(StringUtils.isNotBlank(bo.getMindBefore()), OaHumanClock::getMindBefore, bo.getMindBefore());
        lqw.eq(StringUtils.isNotBlank(bo.getMindAfter()), OaHumanClock::getMindAfter, bo.getMindAfter());
        lqw.eq(StringUtils.isNotBlank(bo.getFacialRecognitionCheck()), OaHumanClock::getFacialRecognitionCheck, bo.getFacialRecognitionCheck());
        lqw.eq(StringUtils.isNotBlank(bo.getClockScope()), OaHumanClock::getClockScope, bo.getClockScope());
        lqw.eq(StringUtils.isNotBlank(bo.getSelectWhiteList()), OaHumanClock::getSelectWhiteList, bo.getSelectWhiteList());
        lqw.eq(StringUtils.isNotBlank(bo.getSelectReportList()), OaHumanClock::getSelectReportList, bo.getSelectReportList());
        lqw.eq(StringUtils.isNotBlank(bo.getEffectuateType()), OaHumanClock::getEffectuateType, bo.getEffectuateType());
        return lqw;
    }

    /**
     * 新增考勤规则
     */
    @Override
    public Boolean insertByBo(OaHumanClockBo bo) {
        OaHumanClock add = BeanUtil.toBean(bo, OaHumanClock.class);
        if (bo.getEffectuateType().equals("2")){
            OaHumanClockVo oaHumanClockVo = oaHumanClockTempMapper.selectVoById(bo.getId());
            OaHumanClockTemp oaHumanClockTemp = BeanUtil.toBean(bo, OaHumanClockTemp.class);
            if (ObjectUtil.isNotEmpty(oaHumanClockVo)){
                return oaHumanClockTempMapper.updateById(oaHumanClockTemp)>0;
            }else {
                return oaHumanClockTempMapper.insert(oaHumanClockTemp)>0;
            }
        }else {
            validEntityBeforeSave(add);
            boolean flag = baseMapper.insert(add) > 0;
            if (flag) {
                bo.setId(add.getId());
            }
            return flag;
        }
    }

    /**
     * 修改考勤规则
     */
    @Override
    public Boolean updateByBo(OaHumanClockBo bo) {
        OaHumanClock update = BeanUtil.toBean(bo, OaHumanClock.class);
        if (bo.getEffectuateType().equals("2")){
            OaHumanClockVo oaHumanClockVo = oaHumanClockTempMapper.selectVoById(bo.getId());
            OaHumanClockTemp oaHumanClockTemp = BeanUtil.toBean(bo, OaHumanClockTemp.class);
            if (ObjectUtil.isNotEmpty(oaHumanClockVo)){
                return oaHumanClockTempMapper.updateById(oaHumanClockTemp)>0;
            }else {
                return oaHumanClockTempMapper.insert(oaHumanClockTemp)>0;
            }
        }else {
            validEntityBeforeSave(update);
            return baseMapper.updateById(update) > 0;
        }
    }

    @Override
    public Boolean adjustClock(AdjustClockBo bo) throws ParseException {
        String minPattern = "HH:mm";
        //分钟转化
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
        SimpleDateFormat holidayFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        Date date=new Date();
        try {
            date = holidayFormat.parse(bo.getReplaceDate());

        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date);
        calendar1.add(Calendar.DAY_OF_MONTH, -1);
        Date previousDate = calendar1.getTime();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type",bo.getType());
        jsonObject.put("id", UUIdUtils.generateCustomId());
        jsonObject.put("clockDate",bo.getClockDate());
        jsonObject.put("adjustName",bo.getAdjustName());
        jsonObject.put("remark",bo.getRemark());
        //昨天打卡日期
        String format = dateFormatIn.format(previousDate);
        //未修改的原数据
        OaHumanClockCountVo oaHumanClockCountVo = iOaHumanClockCountService.queryById(bo.getId());
//        jsonObject.put("isOutSide",oaHumanClockCountVo.getIsOutside());
        //昨日打卡数据
        OaHumanClockCountVo lastCount = iOaHumanClockCountService.selectLastByUserId(oaHumanClockCountVo.getUserId(), format);
        //考勤规则
        OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(oaHumanClockCountVo.getRuleId());
        //补卡逻辑
        if (bo.getCheckWay().equals("one")){
                //处理打卡时间逻辑
                String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
                JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
                clockTimeList.forEach(d -> {
                    JSONObject m1 = (JSONObject) d;
                    List list = (List) m1.get("checkedWeeks");
                    Calendar calendar  = Calendar.getInstance();
                    calendar.setTime(oaHumanClockCountVo.getCreateTime());
                    int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
                    Integer def;
                    if (list.indexOf(dayOfWeek) != -1) {
                        //拿到打卡时间
                        JSONObject timeArray = (JSONObject) m1.get("timeArray");
                        JSONArray periodList = timeArray.getJSONArray("periodList");
                        String startTimeInfo = timeArray.getString("startTime");
                        String endTimeInfo = timeArray.getString("endTime");
                        Date startTime = null;
                        try {
                            startTime = sdf.parse(startTimeInfo);
                            Date endTime = sdf.parse(endTimeInfo);
                            Date clockDate = sdf.parse(bo.getClockDate());
                            if (bo.getType().equals("上班")){
                                jsonObject.put("standard",startTimeInfo);
                                oaHumanClockCountVo.setStartTime(clockDate);
                                if (clockDate.getTime() - startTime.getTime() > 0) {
                                    //迟到时间
                                    def = Math.toIntExact((clockDate.getTime() - startTime.getTime()) / (60 * 1000));
                                    //是否打开下班晚走，次日早到
                                    if (m1.getBoolean("enableArriveLate")) {
                                        //如果昨天参与了打卡
                                        if (ObjectUtil.isNotEmpty(lastCount)){
                                            if (lastCount.getEndTime()!=null){
                                                Integer lastDef = Math.toIntExact((lastCount.getEndTime().getTime() - endTime.getTime()) / (60 * 1000));

                                                JSONArray arriveLateList = m1.getJSONArray("arriveLateList");
                                                Integer arriveLateMax = 0;
                                                Integer lateMin = 0;
                                                for (Object object : arriveLateList) {
                                                    JSONObject object1 = (JSONObject) object;
                                                    Integer leavesLateMinObject = object1.getInteger("leavesLateMin");
                                                    if (lastDef > leavesLateMinObject && leavesLateMinObject > arriveLateMax) {
                                                        arriveLateMax = leavesLateMinObject;
                                                        lateMin = object1.getInteger("lateMin");
                                                    }
                                                }
                                                def = def - lateMin;
                                            }
                                        }
                                    }

                                    //是否开启弹性上下班
                                    if (m1.getBoolean("enableStress")) {
                                        if (m1.getString("stressRadio").equals("1")) {
                                            Integer integer = m1.getJSONObject("leaveEarlyMinutes").getInteger("startMinutes");
                                            def = def - integer;
                                        }
                                    }
                                    if (def > 0) {
                                        if (oaHumanClockCountVo.getLateCount()==0){
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                                            oaHumanClockCountVo.setLateCount(oaHumanClockCountVo.getLateCount()+1);
                                        }
                                        oaHumanClockCountVo.setLateMinutes(def);
                                        oaHumanClockCountVo.setStartStatus("迟到" + def + "分钟");

                                        jsonObject.put("status","迟到"+def+"分钟");
                                    }else {
                                        if (oaHumanClockCountVo.getLateCount()!=0){
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                            oaHumanClockCountVo.setLateCount(0);
                                            oaHumanClockCountVo.setLateMinutes(0);
                                        }
                                        jsonObject.put("status","正常");
                                        oaHumanClockCountVo.setStartStatus("正常");
                                    }
                                }else {
                                    //迟到次数
                                    if (oaHumanClockCountVo.getLateCount()!=0){
                                        oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                        oaHumanClockCountVo.setLateCount(0);
                                        oaHumanClockCountVo.setLateMinutes(0);
                                    }
                                    jsonObject.put("status","正常");
                                    oaHumanClockCountVo.setStartStatus("正常");
                                }
                            }else {
                                jsonObject.put("standard",endTimeInfo);
                                JSONObject endClock = (JSONObject) periodList.get(1);
                                if (!endClock.getBoolean("isClock")) {
                                    oaHumanClockCountVo.setEndTime(endTime);
                                    oaHumanClockCountVo.setActualWorkHour(oaHumanClockCountVo.getStandardWorkHour());
                                }else {
                                    oaHumanClockCountVo.setEndTime(clockDate);
                                    if (clockDate.getTime() - endTime.getTime() < 0) {
                                        def = Math.toIntExact((endTime.getTime() - clockDate.getTime()) / (60 * 1000));
                                        //是否开启弹性上下班
                                        if (m1.getBoolean("enableStress")) {
                                            if (m1.getString("stressRadio").equals("1")) {
                                                Integer integer = m1.getJSONObject("leaveEarlyMinutes").getInteger("endMinutes");
                                                def = def - integer;

                                            } else if (m1.getString("stressRadio").equals("2")) {
                                                if (oaHumanClockCountVo.getStartTime()!=null) {
                                                    Integer leaveDef = Math.toIntExact((startTime.getTime() - oaHumanClockCountVo.getStartTime().getTime()) / (60 * 1000));
                                                    if (leaveDef > 0) {
                                                        //早到早退
                                                        if (leaveDef >= m1.getJSONObject("mostLeaveMinutes").getInteger("startMinutes")) {
                                                            def = def - m1.getJSONObject("mostLeaveMinutes").getInteger("startMinutes");
                                                        }
                                                    } else {
                                                        //晚到晚走
                                                        if (def < 0) {
                                                                if (def + m1.getJSONObject("mostLeaveMinutes").getInteger("endMinutes") < 0) {
                                                                def = def + leaveDef;
                                                                oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount() - 1);
                                                                oaHumanClockCountVo.setLateCount(oaHumanClockCountVo.getLateCount() + 1);
                                                                oaHumanClockCountVo.setLateMinutes(0);
                                                                oaHumanClockCountVo.setStartStatus("正常");
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        if (def > 0) {
                                            if (oaHumanClockCountVo.getLeaveCount()==0){
                                                oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                                                oaHumanClockCountVo.setLeaveCount(oaHumanClockCountVo.getLeaveCount()+1);
                                            }
                                            oaHumanClockCountVo.setLeaveMinutes(def);
                                            jsonObject.put("status","早退" + def + "分钟");
                                            oaHumanClockCountVo.setEndStatus("早退" + def + "分钟");
                                        }else {
                                            if (oaHumanClockCountVo.getLeaveCount()!=0){
                                                oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                                oaHumanClockCountVo.setLeaveCount(0);
                                                oaHumanClockCountVo.setLeaveMinutes(0);
                                            }
                                            jsonObject.put("status","正常");
                                            oaHumanClockCountVo.setEndStatus("正常");
                                        }
                                    }else {
                                        if (oaHumanClockCountVo.getLeaveCount()!=0){
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                            oaHumanClockCountVo.setLeaveCount(0);
                                            oaHumanClockCountVo.setLeaveMinutes(0);
                                        }
                                        jsonObject.put("status","正常");
                                        oaHumanClockCountVo.setEndStatus("正常");
                                    }
                                }
                            }

                            //是否开启休息时间
                            if (oaHumanClockCountVo.getEndTime()!=null&&oaHumanClockCountVo.getStartTime()!=null){
                                long minPoor = DateUtils.getMinPoor(oaHumanClockCountVo.getEndTime(), oaHumanClockCountVo.getStartTime());
                                if ((Boolean) m1.get("enableRest")) {
                                    JSONObject restTime = (JSONObject) m1.get("restTime");
                                    Date startTime1 = dateFormat.parse(restTime.getString("startTime"));
                                    Date endTime1 = dateFormat.parse(restTime.getString("endTime"));
                                    if (DateUtils.getMinPoor(oaHumanClockCountVo.getEndTime(), startTime1)>0){
                                        long minPoor1 = DateUtils.getMinPoor(endTime1, startTime1);
                                        long minutes = minPoor - minPoor1;
                                        double hours = minutes / 60.0;
                                        DecimalFormat df = new DecimalFormat("#.0");
                                        String formattedHours = df.format(hours);
                                        oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                                    }else {
                                        double hours = minPoor / 60.0;
                                        DecimalFormat df = new DecimalFormat("#.0");
                                        String formattedHours = df.format(hours);
                                        oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                                    }
                                } else {
                                    double hours = minPoor / 60.0;
                                    DecimalFormat df = new DecimalFormat("#.0");
                                    String formattedHours = df.format(hours);
                                    oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                                }
                            }
                        } catch (ParseException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            if (oaHumanClockCountVo.getStartTime()==null&&oaHumanClockCountVo.getEndTime()==null){
                if (oaHumanClockCountVo.getAbsentCount()==0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                    oaHumanClockCountVo.setAbsentCount(oaHumanClockCountVo.getAbsentCount()+1);
                    Double standard = oaHumanClockCountVo.getStandardWorkHour();
                    int round =(int) (standard * 60);
                    oaHumanClockCountVo.setAbsentMinutes(round);
                }else if (oaHumanClockCountVo.getAbsentCount()==1){
                    Double standard = oaHumanClockCountVo.getStandardWorkHour();
                    int round =(int) (standard * 60);
                    oaHumanClockCountVo.setAbsentMinutes(round);
                }
            }else if (oaHumanClockCountVo.getStartTime()==null||oaHumanClockCountVo.getEndTime()==null){
                if (oaHumanClockCountVo.getLackCount()==0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                    oaHumanClockCountVo.setLackCount(oaHumanClockCountVo.getLackCount()+1);
                }
                //消除旷工记录
                if (oaHumanClockCountVo.getAbsentCount()!=0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                    oaHumanClockCountVo.setAbsentCount(0);
                    oaHumanClockCountVo.setAbsentMinutes(0);
                }
            }else if (oaHumanClockCountVo.getStartTime()!=null&&oaHumanClockCountVo.getEndTime()!=null){
                //消除旷工记录
                if (oaHumanClockCountVo.getAbsentCount()!=0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                    oaHumanClockCountVo.setAbsentCount(0);
                    oaHumanClockCountVo.setAbsentMinutes(0);
                }
                if (oaHumanClockCountVo.getLackCount()!=0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                    oaHumanClockCountVo.setLackCount(0);
                    oaHumanClockCountVo.setLackCount(0);
                }
            }

            String addressTemp="";
            if (oaHumanClockCountVo.getLateCount()!=0){
                addressTemp="迟到"+oaHumanClockCountVo.getLateMinutes()+"分钟";
            }
            if (oaHumanClockCountVo.getLeaveMinutes()!=0){
                addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"早退"+oaHumanClockCountVo.getLeaveMinutes()+"分钟";
            }
            if (oaHumanClockCountVo.getAddressAbnormalCount()!=0){
                addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"地点异常"+oaHumanClockCountVo.getAddressAbnormalCount()+"次";
            }
            if (oaHumanClockCountVo.getAbsentCount()!=0){
                addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"旷工"+oaHumanClockCountVo.getAbsentMinutes()+"分钟";
            }
            if (oaHumanClockCountVo.getLackCount()!=0){
                addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"缺卡"+oaHumanClockCountVo.getLackCount()+"次";
            }
            if (StringUtils.isBlank(addressTemp)){
                addressTemp="正常";
            }
            oaHumanClockCountVo.setAdjustName(addressTemp);
            String clockListInfo = oaHumanClockCountVo.getClockList();
            JSONArray clockList = JSON.parseArray(clockListInfo);
            if (CollectionUtil.isEmpty(clockList)){
                clockList=new JSONArray();
            }
            List type = clockList.stream().filter(d -> {
                JSONObject d1 = (JSONObject) d;
                return !d1.get("type").equals(bo.getType());
            }).collect(Collectors.toList());
            JSONArray objects = new JSONArray(type);
            objects.add(jsonObject);
            List collect = objects.stream().filter(d -> {
                JSONObject d1 = (JSONObject) d;
                return d1.get("clockDate")!=null;
            }).collect(Collectors.toList());
            oaHumanClockCountVo.setClockCount(collect.size());
            oaHumanClockCountVo.setClockList(String.valueOf(objects));
            OaHumanClockCountBo bean = BeanUtil.toBean(oaHumanClockCountVo, OaHumanClockCountBo.class);
            return iOaHumanClockCountService.updateByBo(bean);
        }else if (bo.getCheckWay().equals("two")){
            //缺卡逻辑
            String clockListInfo = oaHumanClockCountVo.getClockList();
            JSONArray clockList = JSON.parseArray(clockListInfo);
            List<Object> collect = clockList.stream().filter(d -> {
                JSONObject d1 = (JSONObject) d;
                return !d1.get("id").toString().equals(bo.getReplaceId())&&StringUtils.isNotBlank(d1.getString("clockDate"));
            }).collect(Collectors.toList());
            clockList=new JSONArray(collect);
            Comparator<JSONObject> timeComparator = Comparator.comparing(json -> LocalTime.parse(json.getString("clockDate"), DateTimeFormatter.ofPattern("HH:mm")));
            //上班
            List<Object> workList = clockList.stream().filter(d -> {
                JSONObject d1 = (JSONObject) d;
                return d1.get("type").toString().equals("上班");
            }).collect(Collectors.toList());
            JSONArray workInfoList = new JSONArray(workList);
            workInfoList.sort((o1,o2)->timeComparator.compare((JSONObject) o1, (JSONObject) o2));
            if (CollectionUtil.isNotEmpty(workInfoList)){
                JSONObject workInfo = (JSONObject)workInfoList.get(0);
                if (StringUtils.isNotBlank(workInfo.get("clockDate").toString())){
                    String clockInfoDate = workInfo.get("clockDate").toString();
                    Date clockDate = sdf.parse(clockInfoDate);
                    oaHumanClockCountVo.setStartTime(clockDate);
                }
            }else {
                oaHumanClockCountVo.setStartTime(null);
            }
            //下班
            List<Object> offList = clockList.stream().filter(d -> {
                JSONObject d1 = (JSONObject) d;
                return d1.get("type").toString().equals("下班");
            }).collect(Collectors.toList());
            JSONArray offInfoList = new JSONArray(offList);
            offInfoList.sort((o1,o2)->timeComparator.reversed().compare((JSONObject) o1, (JSONObject) o2));
            if (CollectionUtil.isNotEmpty(offInfoList)){
                JSONObject offInfo = (JSONObject)offInfoList.get(0);
                //判断是否为打卡数据
                if (ObjectUtil.isNotEmpty(offInfo.get("clockDate"))){
                    String clockInfoDate = offInfo.get("clockDate").toString();
                    Date clockDate = sdf.parse(clockInfoDate);
                    oaHumanClockCountVo.setEndTime(clockDate);
                }
            }else {
                oaHumanClockCountVo.setEndTime(null);
            }
            //获取打卡次数
            oaHumanClockCountVo.setClockCount(oaHumanClockCountVo.getClockCount()-1);
            //处理打卡时间逻辑
            String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
            JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);

            JSONArray finalClockList = clockList;
            clockTimeList.forEach(d -> {
                JSONObject m1 = (JSONObject) d;
                List list = (List) m1.get("checkedWeeks");
                Calendar calendar  = Calendar.getInstance();
                calendar.setTime(oaHumanClockCountVo.getCreateTime());
                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
                Integer def;
                if (list.indexOf(dayOfWeek) != -1) {
                    //拿到打卡时间
                    JSONObject timeArray = (JSONObject) m1.get("timeArray");
                    JSONArray periodList = timeArray.getJSONArray("periodList");
                    String startTimeInfo = timeArray.getString("startTime");
                    String endTimeInfo = timeArray.getString("endTime");
                    Date startTime;
                    try {
                        startTime = sdf.parse(startTimeInfo);
                        Date endTime = sdf.parse(endTimeInfo);
                        if (oaHumanClockCountVo.getStartTime()!=null){
                            Date clockDate = oaHumanClockCountVo.getStartTime();
                            if (clockDate.getTime() - startTime.getTime() > 0) {
                                //迟到时间
                                def = Math.toIntExact((clockDate.getTime() - startTime.getTime()) / (60 * 1000));
                                //是否打开下班晚走，次日早到
                                if (m1.getBoolean("enableArriveLate")) {
                                    //如果昨天参与了打卡
                                    if (ObjectUtil.isNotEmpty(lastCount)){
                                        if (lastCount.getEndTime()!=null){
                                            Integer lastDef = Math.toIntExact((lastCount.getEndTime().getTime() - endTime.getTime()) / (60 * 1000));

                                            JSONArray arriveLateList = m1.getJSONArray("arriveLateList");
                                            Integer arriveLateMax = 0;
                                            Integer lateMin = 0;
                                            for (Object object : arriveLateList) {
                                                JSONObject object1 = (JSONObject) object;
                                                Integer leavesLateMinObject = object1.getInteger("leavesLateMin");
                                                if (lastDef > leavesLateMinObject && leavesLateMinObject > arriveLateMax) {
                                                    arriveLateMax = leavesLateMinObject;
                                                    lateMin = object1.getInteger("lateMin");
                                                }
                                            }
                                            def = def - lateMin;
                                        }
                                    }
                                }

                                //是否开启弹性上下班
                                if (m1.getBoolean("enableStress")) {
                                    if (m1.getString("stressRadio").equals("1")) {
                                        Integer integer = m1.getJSONObject("leaveEarlyMinutes").getInteger("startMinutes");
                                        def = def - integer;
                                    }
                                }
                                if (def > 0) {
                                    if (oaHumanClockCountVo.getLateCount()==0){
                                        oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                                        oaHumanClockCountVo.setLateCount(1);
                                    }
                                    oaHumanClockCountVo.setLateMinutes(def);
                                    oaHumanClockCountVo.setStartStatus("迟到" + def + "分钟");
                                    jsonObject.put("status","迟到"+def+"分钟");
                                }else {
                                    if (oaHumanClockCountVo.getLateCount()!=0){
                                        oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                        oaHumanClockCountVo.setLateCount(0);
                                        oaHumanClockCountVo.setLateMinutes(0);
                                    }
                                    jsonObject.put("status","正常");
                                    oaHumanClockCountVo.setStartStatus("正常");
                                }
                            }else {
                                //迟到次数
                                if (oaHumanClockCountVo.getLateCount()!=0){
                                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                    oaHumanClockCountVo.setLateCount(0);
                                    oaHumanClockCountVo.setLateMinutes(0);
                                }
                                jsonObject.put("status","正常");
                                oaHumanClockCountVo.setStartStatus("正常");
                            }
                        }else {
                            oaHumanClockCountVo.setEndStatus("缺卡("+startTimeInfo+")");
                            JSONObject jsonObject2 = new JSONObject();
                            jsonObject2.put("type","上班");
                            jsonObject2.put("status","缺卡");
                            jsonObject2.put("standard",startTimeInfo);
                            jsonObject2.put("id", UUIdUtils.generateCustomId());
                            finalClockList.add(jsonObject2);
                        }
                        if (oaHumanClockCountVo.getEndTime()!=null) {
                            Date clockDate = oaHumanClockCountVo.getEndTime();
                            JSONObject endClock = (JSONObject) periodList.get(1);
                            if (!endClock.getBoolean("isClock")) {
                                oaHumanClockCountVo.setEndTime(endTime);
                                oaHumanClockCountVo.setActualWorkHour(oaHumanClockCountVo.getStandardWorkHour());
                            }else {
                                if (clockDate.getTime() - endTime.getTime() < 0) {
                                    def = Math.toIntExact((endTime.getTime() - clockDate.getTime()) / (60 * 1000));
                                    //是否开启弹性上下班
                                    if (m1.getBoolean("enableStress")) {
                                        if (m1.getString("stressRadio").equals("1")) {
                                            Integer integer = m1.getJSONObject("leaveEarlyMinutes").getInteger("endMinutes");
                                            def = def - integer;

                                        } else if (m1.getString("stressRadio").equals("2")) {
                                            if (oaHumanClockCountVo.getStartTime()!=null) {
                                                Integer leaveDef = Math.toIntExact((startTime.getTime() - oaHumanClockCountVo.getStartTime().getTime()) / (60 * 1000));
                                                if (leaveDef > 0) {
                                                    //早到早退
                                                    if (leaveDef >= m1.getJSONObject("mostLeaveMinutes").getInteger("startMinutes")) {
                                                        def = def - m1.getJSONObject("mostLeaveMinutes").getInteger("startMinutes");
                                                    }
                                                } else {
                                                    //晚到晚走
                                                    if (def < 0) {
                                                        if (def + m1.getJSONObject("mostLeaveMinutes").getInteger("endMinutes") < 0) {
                                                            def = def + leaveDef;
                                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount() - 1);
                                                            oaHumanClockCountVo.setLateCount(1);
                                                            oaHumanClockCountVo.setLateMinutes(0);
                                                            oaHumanClockCountVo.setStartStatus("正常");
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (def > 0) {
                                        if (oaHumanClockCountVo.getLeaveCount()==0){
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                                            oaHumanClockCountVo.setLeaveCount(1);
                                        }
                                        oaHumanClockCountVo.setLeaveMinutes(def);
                                        jsonObject.put("status","早退" + def + "分钟");
                                        oaHumanClockCountVo.setEndStatus("早退" + def + "分钟");
                                    }else {
                                        if (oaHumanClockCountVo.getLeaveCount()!=0){
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                            oaHumanClockCountVo.setLeaveCount(0);
                                            oaHumanClockCountVo.setLeaveMinutes(0);
                                        }
                                        jsonObject.put("status","正常");
                                        oaHumanClockCountVo.setEndStatus("正常");
                                    }
                                }else {
                                    if (oaHumanClockCountVo.getLeaveCount()!=0){
                                        oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                        oaHumanClockCountVo.setLeaveCount(0);
                                        oaHumanClockCountVo.setLeaveMinutes(0);
                                    }
                                    jsonObject.put("status","正常");
                                    oaHumanClockCountVo.setEndStatus("正常");
                                }
                            }
                        }else {
                            oaHumanClockCountVo.setEndStatus("缺卡("+endTimeInfo+")");
                            JSONObject jsonObject2 = new JSONObject();
                            jsonObject2.put("id", UUIdUtils.generateCustomId());
                            jsonObject2.put("type","下班");
                            jsonObject2.put("status","缺卡");
                            jsonObject2.put("standard",endTimeInfo);
                            finalClockList.add(jsonObject2);
                        }

                        //是否开启休息时间
                        if (oaHumanClockCountVo.getEndTime()!=null&&oaHumanClockCountVo.getStartTime()!=null){
                            long minPoor = DateUtils.getMinPoor(oaHumanClockCountVo.getEndTime(), oaHumanClockCountVo.getStartTime());
                            if ((Boolean) m1.get("enableRest")) {
                                JSONObject restTime = (JSONObject) m1.get("restTime");
                                Date startTime1 = dateFormat.parse(restTime.getString("startTime"));
                                Date endTime1 = dateFormat.parse(restTime.getString("endTime"));
                                long minPoor1 = DateUtils.getMinPoor(endTime1, startTime1);
                                long minutes = minPoor - minPoor1;
                                double hours = minutes / 60.0;
                                DecimalFormat df = new DecimalFormat("#.0");
                                String formattedHours = df.format(hours);
                                oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                            } else {
                                double hours = minPoor / 60.0;
                                DecimalFormat df = new DecimalFormat("#.0");
                                String formattedHours = df.format(hours);
                                oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                            }
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            if (oaHumanClockCountVo.getStartTime()==null&&oaHumanClockCountVo.getEndTime()==null){
                if (oaHumanClockCountVo.getAbsentCount()==0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                    oaHumanClockCountVo.setAbsentCount(oaHumanClockCountVo.getAbsentCount()+1);
                    Double standard = oaHumanClockCountVo.getStandardWorkHour();
                    int round =(int) (standard * 60);
                    oaHumanClockCountVo.setAbsentMinutes(round);
                }else if (oaHumanClockCountVo.getAbsentCount()==1){
                    Double standard = oaHumanClockCountVo.getStandardWorkHour();
                    int round =(int) (standard * 60);
                    oaHumanClockCountVo.setAbsentMinutes(round);
//                    oaHumanClockCountVo.setAdjustName("旷工"+round+"分钟");
                }
            }else if (oaHumanClockCountVo.getStartTime()==null||oaHumanClockCountVo.getEndTime()==null){
                oaHumanClockCountVo.setStandardWorkHour(null);
                if (oaHumanClockCountVo.getLackCount()==0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                    oaHumanClockCountVo.setLackCount(1);
                }
                //消除旷工记录
                if (oaHumanClockCountVo.getAbsentCount()!=0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                    oaHumanClockCountVo.setAbsentCount(0);
                    oaHumanClockCountVo.setAbsentMinutes(0);
                }
            }else if (oaHumanClockCountVo.getStartTime()!=null&&oaHumanClockCountVo.getEndTime()!=null){
                oaHumanClockCountVo.setStandardWorkHour(null);
                //消除旷工记录
                if (oaHumanClockCountVo.getAbsentCount()!=0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                    oaHumanClockCountVo.setAbsentCount(0);
                    oaHumanClockCountVo.setAbsentMinutes(0);
                }
                if (oaHumanClockCountVo.getLackCount()!=0){
                    oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                    oaHumanClockCountVo.setLackCount(0);
                    oaHumanClockCountVo.setLackCount(0);
                }
            }

            {
                String addressTemp="";
                if (oaHumanClockCountVo.getLateCount()!=0){
                    addressTemp="迟到"+oaHumanClockCountVo.getLateMinutes()+"分钟";
                }
                if (oaHumanClockCountVo.getLeaveMinutes()!=0){
                    addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"早退"+oaHumanClockCountVo.getLeaveMinutes()+"分钟";
                }
                if (oaHumanClockCountVo.getAddressAbnormalCount()!=0){
                    addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"地点异常"+oaHumanClockCountVo.getAddressAbnormalCount()+"次";
                }
                if (oaHumanClockCountVo.getAbsentCount()!=0){
                    addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"旷工"+oaHumanClockCountVo.getAbsentMinutes()+"分钟";
                }
                if (oaHumanClockCountVo.getLackCount()!=0){
                    addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"缺卡"+oaHumanClockCountVo.getLackCount()+"次";
                }
                if (StringUtils.isBlank(addressTemp)){
                    addressTemp="正常";
                }
                oaHumanClockCountVo.setAdjustName(addressTemp);
            }



            //处理打卡记录
            oaHumanClockCountVo.setClockList(String.valueOf(finalClockList));
            OaHumanClockCountBo bean = BeanUtil.toBean(oaHumanClockCountVo, OaHumanClockCountBo.class);
            Boolean aBoolean = iOaHumanClockCountService.updateByBo(bean);
            if (bean.getStartTime()==null){
                iOaHumanClockCountService.cleanStartTime(bean.getId());
            }
            if (bean.getEndDate()==null){
                iOaHumanClockCountService.cleanEndTime(bean.getId());
            }
            return aBoolean;
        }
        return false;
    }


    @Override
    public void adjustApply(OaHumanReplaceVo vo) throws ParseException {
        SimpleDateFormat format =new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat format3 =new SimpleDateFormat("yyyy-MM-dd");
        String replaceDate = format.format(vo.getReplaceTime());
        SimpleDateFormat format2 = new SimpleDateFormat("HH:mm");

        //补卡时间
        String clockDate = format2.format(vo.getReplaceTime());
        String replaceDate2 = format3.format(vo.getReplaceTime());
        OaHumanClockCountVo oaHumanClockCountVo = iOaHumanClockCountService.selectLastByUserId(vo.getUserId().toString(), replaceDate);
        oaHumanClockCountVo.setReplaceCount(oaHumanClockCountVo.getReplaceCount()+1);
        OaHumanClockCountBo bean = BeanUtil.toBean(oaHumanClockCountVo, OaHumanClockCountBo.class);
        iOaHumanClockCountService.updateByBo(bean);
        AdjustClockBo adjustClockBo = new AdjustClockBo();
        adjustClockBo.setType(vo.getReplaceType());
        adjustClockBo.setReplaceDate(replaceDate2);
        adjustClockBo.setClockDate(clockDate);
        adjustClockBo.setId(oaHumanClockCountVo.getId());
        adjustClockBo.setCheckWay("one");
        adjustClock(adjustClockBo);
    }
    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OaHumanClock entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除考勤规则
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    //获取用户补卡信息
    @Override
    public JSONObject getUserReplaceInfo(String userId,String month){
        OaHumanClock oaHumanClockVo = baseMapper.selectOne(new LambdaQueryWrapper<>());
        JSONObject jsonObject = new JSONObject();
        if (oaHumanClockVo==null){
            jsonObject.put("hasData",false);
        }else {
            String clockTypeList = oaHumanClockVo.getClockTypeList();
            JSONArray array = JSON.parseArray(clockTypeList);
            List<ClockUserDto> userList = new ArrayList<>();
            List<String> deptList = new ArrayList<>();
            List<ClockUserDto> finalUserList = userList;
            array.forEach(d->{
                JSONObject d1 = (JSONObject) d;
                if (ObjectUtil.isNotNull(d1.get("label"))){
                    deptList.add(d1.get("id").toString());
                }else {
                    ClockUserDto clockUserDto = new ClockUserDto();
                    clockUserDto.setUserId(d1.get("userId").toString());
                    clockUserDto.setNickName(d1.get("nickName").toString());
                    clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                    JSONObject dept = (JSONObject) d1.get("dept");
                    clockUserDto.setDeptName(dept.getString("deptName"));
                    finalUserList.add(clockUserDto);
                }
            });
            if (CollectionUtil.isNotEmpty(deptList)){
                String join = String.join(",", deptList);
                List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
                finalUserList.addAll(list);
            }
            Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
            userList=new ArrayList<>(distinctSet);
            userList = userList.stream().filter(d -> d.getUserId().equals(userId)).collect(Collectors.toList());
            SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
            SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
            if (CollectionUtil.isNotEmpty(userList)){
                Date date = null;
                if (oaHumanClockVo.getEnableReplaceCard()){
                    try {
                        date = inputDateFormat.parse(month);
                        String outputDate = outputDateFormat.format(date);
                        int replaceCountByIdAndMonth = iOaHumanClockCountService.getReplaceCountByIdAndMonth(userId, outputDate);
                        //每月允许打卡次数
                        int replaceNumberPermon = Integer.parseInt(oaHumanClockVo.getReplaceNumberPermon());
                        jsonObject.put("replaceCountByIdAndMonth",replaceCountByIdAndMonth);
                        //剩余打卡次数
                        int remainTotal = replaceNumberPermon - replaceCountByIdAndMonth;
                        if (remainTotal>0){
                            jsonObject.put("remainTotal",remainTotal);
                            jsonObject.put("permit",true);
                        }else {
                            jsonObject.put("remainTotal",0);
                            jsonObject.put("permit",false);
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                }else {
                    jsonObject.put("permit",false);
                }
                jsonObject.put("hasData",true);
            }else {
                jsonObject.put("hasData",false);
            }
        }
        return jsonObject;
    }

    //判断是否有打卡的机会
    @Override
    public Boolean checkDateHasChance(String userId,Date replaceDate){
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        String format = dateFormatIn.format(replaceDate);
        OaHumanClockCountVo oaHumanClockCountVo =iOaHumanClockCountService.selectLastByUserId(userId,format);
        OaHumanClockVo oaHumanClockVo = queryById(oaHumanClockCountVo.getRuleId());
        Date date = new Date();
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(replaceDate);
        cal2.setTime(date);
        // 计算两个日期之间的时间差
        long differenceInMillis = Math.abs(cal2.getTimeInMillis()-cal1.getTimeInMillis());

        // 将时间差转换为天数
        int differenceInDays = (int)differenceInMillis / (24 * 60 * 60 * 1000);
        String timeLimit = oaHumanClockVo.getTimeLimit();
        int limit = Integer.parseInt(timeLimit);
        if (limit==0){
            return true;
        }else {
            if (limit>differenceInDays){
                return true;
            }else {
                return false;
            }
        }
    }


    /**
     * 用户打卡
     * @param bo
     */
    @Override
    public R<Boolean> clock(ClockUserInfoBo bo) {
        AtomicReference<Boolean> hasRightTimeFlag= new AtomicReference<>(true);

        //判断是否为节假日时间
        Date now = new Date();
        String minPattern = "HH:mm";
        SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat holidayFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = holidayFormat.format(now);
        // 获取当前日期
        Calendar calendar = Calendar.getInstance();
        // 将日期减去一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        // 将Calendar对象转换为Date对象
        Date yesterday = calendar.getTime();
        String yesterdayString = dateFormatIn.format(yesterday);
        OaHoliday oaHoliday = iOaHolidayService.selectIsHoliday(dateString);
        String format = dateFormatIn.format(now);
        if (ObjectUtil.isNotEmpty(oaHoliday)) {
            return R.fail("休息时间,无需打卡");
        } else {
            OaHumanClockCountVo oaHumanClockCountVo =iOaHumanClockCountService.selectLastByUserId(bo.getUserId(),format);
            if (oaHumanClockCountVo==null){
                return R.fail("用户不在考勤规则里");
            }
            OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(oaHumanClockCountVo.getRuleId());
            //打卡地点
            String clockLocationListInfo = oaHumanClockVo.getClockLocationList();
            JSONArray clockLocationList = JSON.parseArray(clockLocationListInfo);
            Double range=0.00;
            //外勤
            if (!oaHumanClockCountVo.getIsOutside()&&!bo.getIsOutside()){
                for (Object clockLocationInfo : clockLocationList) {
                    JSONObject clockLocation = (JSONObject) clockLocationInfo;
                    double clockLongitude = clockLocation.getDouble("longitude");
                    double clockLatitude = clockLocation.getDouble("latitude");
                    double distance = DistanceUtils.calculateDistance(clockLatitude, clockLongitude, bo.getLatitude(), bo.getLongitude());
                    if (distance>clockLocation.getDouble("range")){
                        if (oaHumanClockVo.getClockScope().equals("3")){
                            range=distance;
                        }else if (oaHumanClockVo.getClockScope().equals("1")){
                            oaHumanClockCountVo.setAddressAbnormalCount(oaHumanClockCountVo.getAddressAbnormalCount()+1);
                        }
                    }else {
                        range=0.00;
                        break;
                    }
                }

                if (range>0.00){
                    return R.fail("不在打卡范围内");
                }
            }
            //分钟转化
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            //处理打卡时间逻辑
            String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
            JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
            clockTimeList.forEach(d -> {
                JSONObject m1 = (JSONObject) d;
                List list = (List) m1.get("checkedWeeks");
                Calendar instance = Calendar.getInstance();
                int i = (instance.get(Calendar.DAY_OF_WEEK) + 6) % 7;
                Integer def;
                if (list.contains(i)) {
                    //拿到打卡时间
                    JSONObject timeArray = (JSONObject) m1.get("timeArray");
                    //上下班打卡时段
                    JSONArray periodList = timeArray.getJSONArray("periodList");
                    String startTimeInfo = timeArray.getString("startTime");
                    String endTimeInfo = timeArray.getString("endTime");
                    oaHumanClockCountVo.setClockCount(oaHumanClockCountVo.getClockCount()+1);
                    //  生成默认数据时 Todo  判断是否可打卡  是否需要打卡
                    //上班规定时间
                    try {
                        Date startTime = sdf.parse(startTimeInfo);
                        Date endTime = sdf.parse(endTimeInfo);
                        Date clockDate = bo.getClockDate();
                        //获取当前打卡者上一天打卡数据
                        OaHumanClockCountVo lastCount = iOaHumanClockCountService.selectLastByUserId(bo.getUserId(), yesterdayString);
                        //添加打卡记录
                        String clockListInfo = oaHumanClockCountVo.getClockList();
                        JSONArray clockList=new JSONArray();
                        if (StringUtils.isNotBlank(clockListInfo)){
                            clockList = JSON.parseArray(clockListInfo);
                        }
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("id", UUIdUtils.generateCustomId());
                        jsonObject.put("address",bo.getAddress());
                        jsonObject.put("remark",bo.getRemarks());
                        jsonObject.put("clockDate",sdf.format(bo.getClockDate()));
                        jsonObject.put("isOutSide",bo.getIsOutside());
                        if (bo.getIsOutside()){
                            oaHumanClockCountVo.setIsOutside(true);
                            jsonObject.put("attachment",bo.getAttachment());
                            jsonObject.put("outSideReason",bo.getOutSideReason());
                        }
                        JSONObject startClock = (JSONObject) periodList.get(0);
                        JSONObject endClock = (JSONObject) periodList.get(1);
                        String offStartInfo = endClock.getString("startTime");
                        Date offStart = sdf.parse(offStartInfo);
                        String offEndInfo = endClock.getString("endTime");
                        Date offEnd = sdf.parse(offEndInfo);
                        String workStartInfo = startClock.getString("startTime");
                        Date workStart = sdf.parse(workStartInfo);
                        String workEndInfo = startClock.getString("endTime");
                        Date workEnd = sdf.parse(workEndInfo);
                        if (ObjectUtil.isEmpty(oaHumanClockCountVo.getStartTime()) && clockDate.getTime() <= workEnd.getTime()) {
                            //上班打卡逻辑
                            jsonObject.put("type","上班");
                            jsonObject.put("standard",sdf.format(startTime));
                            //判断上班
                            if (!startClock.getBoolean("isClock")) {
                                oaHumanClockCountVo.setStartTime(startTime);
                            } else {
                                if (clockDate.getTime() > workStart.getTime() && clockDate.getTime() < workEnd.getTime()) {
                                    oaHumanClockCountVo.setStartTime(clockDate);
                                    if (clockDate.getTime() - startTime.getTime() > 0) {
                                        //迟到时间
                                        def = Math.toIntExact((clockDate.getTime() - startTime.getTime()) / (60 * 1000));
                                        //是否打开下班晚走，次日早到
                                        if (m1.getBoolean("enableArriveLate")) {
                                            //如果昨天参与了打卡
                                            if (ObjectUtil.isNotEmpty(lastCount)) {
                                                if (lastCount.getEndTime()!=null){
                                                    Integer lastDef = Math.toIntExact((lastCount.getEndTime().getTime() - endTime.getTime()) / (60 * 1000));

                                                    JSONArray arriveLateList = m1.getJSONArray("arriveLateList");
                                                    Integer arriveLateMax = 0;
                                                    Integer lateMin = 0;
                                                    for (Object object : arriveLateList) {
                                                        JSONObject object1 = (JSONObject) object;
                                                        Integer leavesLateMinObject = object1.getInteger("leavesLateMin");
                                                        if (lastDef > leavesLateMinObject && leavesLateMinObject > arriveLateMax) {
                                                            arriveLateMax = leavesLateMinObject;
                                                            lateMin = object1.getInteger("lateMin");
                                                        }
                                                    }
                                                    def = def - lateMin;
                                                }
                                            }
                                        }
                                        //是否开启弹性上下班
                                        if (m1.getBoolean("enableStress")) {
                                            if (m1.getString("stressRadio").equals("1")) {
                                                Integer integer = m1.getJSONObject("leaveEarlyMinutes").getInteger("startMinutes");
                                                def = def - integer;
                                            }
                                        }
                                        if (def > 0) {
                                            jsonObject.put("status","迟到" + def + "分钟");
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                                            oaHumanClockCountVo.setLateCount(1);
                                            oaHumanClockCountVo.setLateMinutes(def);
                                            oaHumanClockCountVo.setStartStatus("迟到" + def + "分钟");
                                        }else {
                                            oaHumanClockCountVo.setStartStatus("正常");
                                            jsonObject.put("status","正常");
                                        }
                                    }else {
                                        jsonObject.put("status","正常");
                                        oaHumanClockCountVo.setStartStatus("正常");
                                    }
                                } else {
                                    hasRightTimeFlag.set(false);
                                    R.fail("不在打卡时间范围内");
                                }
                            }
                        } else {
                            //判断下班
                            jsonObject.put("standard",sdf.format(endTime));
                            jsonObject.put("type","下班");
                            if (!endClock.getBoolean("isClock")) {
                                oaHumanClockCountVo.setEndTime(endTime);
                                oaHumanClockCountVo.setActualWorkHour(oaHumanClockCountVo.getStandardWorkHour());
                            }else {
                                oaHumanClockCountVo.setEndTime(clockDate);
                                if (oaHumanClockCountVo.getStartTime()!=null){
                                    long minPoor = DateUtils.getMinPoor(oaHumanClockCountVo.getEndTime(), oaHumanClockCountVo.getStartTime());
                                    //是否开启休息时间
                                    if ((Boolean) m1.get("enableRest")) {
                                        JSONObject restTime = (JSONObject) m1.get("restTime");
                                        Date startTime1 = dateFormat.parse(restTime.getString("startTime"));
                                        Date endTime1 = dateFormat.parse(restTime.getString("endTime"));
                                        if (DateUtils.getMinPoor(oaHumanClockCountVo.getEndTime(), startTime1)>0){
                                            long minPoor1 = DateUtils.getMinPoor(endTime1, startTime1);
                                            long minutes = minPoor - minPoor1;
                                            double hours = minutes / 60.0;
                                            DecimalFormat df = new DecimalFormat("#.0");
                                            String formattedHours = df.format(hours);
                                            oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                                        }else {
                                            double hours = minPoor / 60.0;
                                            DecimalFormat df = new DecimalFormat("#.0");
                                            String formattedHours = df.format(hours);
                                            oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                                        }
                                    } else {
                                        double hours = minPoor / 60.0;
                                        DecimalFormat df = new DecimalFormat("#.0");
                                        String formattedHours = df.format(hours);
                                        oaHumanClockCountVo.setActualWorkHour(Double.valueOf(formattedHours));
                                    }
                                }
                                if (clockDate.getTime() > offStart.getTime() && clockDate.getTime() < offEnd.getTime()) {
                                    if (clockDate.getTime() - endTime.getTime() < 0) {
                                        def = Math.toIntExact((endTime.getTime() - clockDate.getTime()) / (60 * 1000));
                                        //是否开启弹性上下班
                                        if (m1.getBoolean("enableStress")) {
                                            if (m1.getString("stressRadio").equals("1")) {
                                                Integer integer = m1.getJSONObject("leaveEarlyMinutes").getInteger("endMinutes");
                                                def = def - integer;

                                            } else if (m1.getString("stressRadio").equals("2")) {
                                                Integer leaveDef = Math.toIntExact((startTime.getTime() - oaHumanClockCountVo.getStartTime().getTime()) / (60 * 1000));
                                                if (leaveDef > 0) {
                                                    //早到早退
                                                    if (leaveDef >= m1.getJSONObject("mostLeaveMinutes").getInteger("startMinutes")) {
                                                        def = def - m1.getJSONObject("mostLeaveMinutes").getInteger("startMinutes");
                                                    }
                                                }else {
                                                    //晚到晚走
                                                    if (def<0){
                                                        if (def+m1.getJSONObject("mostLeaveMinutes").getInteger("endMinutes")<0) {
                                                            def = def + leaveDef;
                                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()-1);
                                                            oaHumanClockCountVo.setLateCount(oaHumanClockCountVo.getLateCount()+1);
                                                            oaHumanClockCountVo.setLateMinutes(0);
                                                            oaHumanClockCountVo.setStartStatus("正常");
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        if (def > 0) {
                                            oaHumanClockCountVo.setAbnormalCount(oaHumanClockCountVo.getAbnormalCount()+1);
                                            oaHumanClockCountVo.setLeaveCount(1);
                                            oaHumanClockCountVo.setLeaveMinutes(def);
                                            jsonObject.put("status","早退" + def + "分钟");
                                            oaHumanClockCountVo.setEndStatus("早退" + def + "分钟");

                                        }else {
                                            jsonObject.put("status","正常");
                                            oaHumanClockCountVo.setEndStatus("正常");
                                        }
                                        if (CollectionUtil.isEmpty(clockList)){
                                            clockList=new JSONArray();
                                        }
                                    }else {
                                        jsonObject.put("status","正常");
                                        oaHumanClockCountVo.setEndStatus("正常");
                                    }
                                } else {
                                    hasRightTimeFlag.set(false);
                                    R.fail("不在打卡时间范围内");
                                }
                            }
                        }
                        clockList.add(jsonObject);
                        oaHumanClockCountVo.setClockList(clockList.toString());
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            if (!hasRightTimeFlag.get()){
                return R.fail("不在打卡时间范围内");
            }
            String addressTemp="";
            if (oaHumanClockCountVo.getLateCount()!=0){
                addressTemp="迟到"+oaHumanClockCountVo.getLateMinutes()+"分钟";
            }
            if (oaHumanClockCountVo.getLeaveMinutes()!=0){
                addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"早退"+oaHumanClockCountVo.getLeaveMinutes()+"分钟";
            }
            if (oaHumanClockCountVo.getAddressAbnormalCount()!=0){
                addressTemp=addressTemp+(StringUtils.isNotBlank(addressTemp)?"、":"")+"地点异常"+oaHumanClockCountVo.getAddressAbnormalCount()+"次";
            }
            if (StringUtils.isBlank(addressTemp)){
                addressTemp="核算中";
            }
            oaHumanClockCountVo.setAdjustName(addressTemp);
            OaHumanClockCountBo bean = BeanUtil.toBean(oaHumanClockCountVo, OaHumanClockCountBo.class);
            return R.ok(iOaHumanClockCountService.updateByBo(bean));
        }
    }


    /**
     * 每日新增数据
     */
//    @Scheduled(cron = "0/20 * * * * ?")
    @Scheduled(cron = "0 10 4 * * ?") // 每天4点10分执行一次
    public void addNormal(){
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        List<OaHumanClock> all = getAll();
        String minPattern = "HH:mm";
        SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
        for (OaHumanClock oaHumanClock : all) {
            //打卡人员：分别处理部门和人员
            String clockTypeList = oaHumanClock.getClockTypeList();
            JSONArray array = JSON.parseArray(clockTypeList);
            List<ClockUserDto> userList = new ArrayList<>();
            List<String> deptList = new ArrayList<>();
            String selectWhiteList = oaHumanClock.getSelectWhiteList();
            List<ClockUserDto> finalUserList = userList;
            array.forEach(d->{
                JSONObject d1 = (JSONObject) d;
                if (ObjectUtil.isNotNull(d1.get("label"))){
                    deptList.add(d1.get("id").toString());
                }else {
                    ClockUserDto clockUserDto = new ClockUserDto();
                    clockUserDto.setUserId(d1.get("userId").toString());
                    clockUserDto.setNickName(d1.get("nickName").toString());
                    clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                    JSONObject dept = (JSONObject) d1.get("dept");
                    clockUserDto.setDeptName(dept.getString("deptName"));
                    finalUserList.add(clockUserDto);
                }
            });
            if (CollectionUtil.isNotEmpty(deptList)){
                String join = String.join(",", deptList);
                List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
                finalUserList.addAll(list);
            }
            Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
            userList=new ArrayList<>(distinctSet);
            //过滤白名单
            JSONArray whiteList = JSON.parseArray(selectWhiteList);
            List<String> whiteUserIdList = whiteList.stream().map(white -> {
                JSONObject white1 = (JSONObject) white;
                return white1.get("userId").toString();
            }).collect(Collectors.toList());
            userList= userList.stream().filter(white-> whiteUserIdList.indexOf(white.getUserId())==-1).collect(Collectors.toList());
            Date now = new Date();
            String format = dateFormatIn.format(now);
            userList.forEach(d->{
                OaHumanClockCountVo oaHumanClockVos =iOaHumanClockCountService.selectLastByUserId(d.getUserId(),format);
                if (ObjectUtil.isEmpty(oaHumanClockVos)) {
                    OaHumanClockCountBo count = new OaHumanClockCountBo();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd EEEE");

                    // 获取当前时间
                    Date currentDate = new Date();

                    // 格式化日期并输出
                    String formattedDate = sdf.format(currentDate);
                    formattedDate = formattedDate.replace("EEEE", "星期");
                    count.setClockDate(formattedDate);
                    count.setUserId(d.getUserId());
                    count.setUserName(d.getNickName());
                    count.setDeptName(d.getDeptName());
                    count.setRoleName(d.getRoleName());
                    count.setRuleId(oaHumanClock.getId());
                    count.setRuleName(oaHumanClock.getRuleName());
                    SimpleDateFormat holidayFormat = new SimpleDateFormat("yyyy-MM-dd");
                    String dateString = holidayFormat.format(now);
                    OaHoliday oaHoliday = iOaHolidayService.selectIsHoliday(dateString);
                    if (ObjectUtil.isEmpty(oaHoliday)) {
                        String clockTimeListInfo = oaHumanClock.getClockTimeList();
                        JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
                        clockTimeList.forEach(m -> {
                            JSONObject m1 = (JSONObject) m;
                            List list = (List) m1.get("checkedWeeks");
                            Calendar instance = Calendar.getInstance();
                            int i = (instance.get(Calendar.DAY_OF_WEEK) + 6) % 7;
                            if (list.indexOf(i) != -1) {
                                JSONObject timeArray = (JSONObject) m1.get("timeArray");
//                                count.setClockShift(timeArray.get("startTime") + "-" + timeArray.get("endTime"));
                                try {
                                    Date startTime = dateFormat.parse(timeArray.get("startTime").toString());
                                    Date endTime = dateFormat.parse(timeArray.get("endTime").toString());
                                    long minPoor = DateUtils.getMinPoor(endTime, startTime);
                                    //是否开启休息时间
                                    if ((Boolean) m1.get("enableRest")) {
                                        JSONObject restTime = (JSONObject) m1.get("restTime");
                                        Date startTime1 = dateFormat.parse(restTime.getString("startTime"));
                                        Date endTime1 = dateFormat.parse(restTime.getString("endTime"));
                                        count.setClockShift(timeArray.get("startTime") + "-"+restTime.getString("startTime")+"、"+restTime.getString("endTime")+"-" + timeArray.get("endTime"));
                                        long minPoor1 = DateUtils.getMinPoor(endTime1, startTime1);
                                        long minutes = minPoor - minPoor1;
                                        double hours = minutes / 60.0;
                                        DecimalFormat df = new DecimalFormat("#.0");
                                        String formattedHours = df.format(hours);
                                        count.setStandardWorkHour(Double.valueOf(formattedHours));
                                    } else {
                                        count.setClockShift(timeArray.get("startTime") + "-" + timeArray.get("endTime"));
                                        double hours = minPoor / 60.0;
                                        DecimalFormat df = new DecimalFormat("#.0");
                                        String formattedHours = df.format(hours);
                                        count.setStandardWorkHour(Double.valueOf(formattedHours));
                                    }
                                } catch (ParseException e) {
                                    throw new RuntimeException(e);
                                }
                                count.setAdjustName("核算中");
                            }
                        });
                    } else {
                        count.setClockShift("休息");
                        count.setAdjustName("正常(休息)");
                    }
                    count.setClockCount(0);
                    String selectOutsideList = oaHumanClock.getSelectOutsideList();
                    JSONArray outsideList = JSON.parseArray(selectOutsideList);
                    if (CollectionUtil.isEmpty(outsideList)){
                        outsideList=new JSONArray();
                    }else {
                        List<String> outsideListList = outsideList.stream().map(white -> {
                            JSONObject white1 = (JSONObject) white;
                            return white1.get("userId").toString();
                        }).collect(Collectors.toList());
                        if (outsideListList.indexOf(d.getUserId())!=-1){
                            count.setIsOutside(true);
                        }else {
                            count.setIsOutside(false);
                        }
                    }
                    iOaHumanClockCountService.insertByBo(count);
                }
            });
        }
    }

//    @Scheduled(cron = "0/20 * * * * ?")
    @Scheduled(cron = "0 51 20 * * ?") // 每分钟执行一次
    public void test(){
        System.out.println("小言你好");
    }

    /**
     * 对昨天已打卡数据进行判断
     */
    @Scheduled(cron = "0 0 4 * * ?") // 每天4点执行一次
//    @Scheduled(cron = "0/20 * * * * ?")
    public void updateLastDayDate(){
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        // 获取当前日期
        Calendar calendar = Calendar.getInstance();
        // 将日期减去一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        // 将Calendar对象转换为Date对象
        Date yesterday = calendar.getTime();
        String yesterdayString = dateFormatIn.format(yesterday);
        List<OaHumanClockCountVo> lastCountList = iOaHumanClockCountService.selectCountByDate(yesterdayString);
        if (CollectionUtil.isNotEmpty(lastCountList)){
            lastCountList.forEach(d->{
                if (!d.getAdjustName().equals("正常(休息)")){
                    if (d.getStartTime()==null&&(d.getEndTime()==null)){
                        if (d.getAbsentCount()==0){
                            d.setAbnormalCount(d.getAbnormalCount()+2);
                            d.setAbsentCount(1);
                            Double standard = d.getStandardWorkHour();
                            int round =(int) (standard * 60);
                            d.setAbsentMinutes(round);
                            d.setAdjustName("旷工"+round+"分钟");
                        }
                    }else if (d.getStartTime()==null||d.getEndTime()==null){
                        if (d.getLateCount()==0){
                            d.setAbnormalCount(d.getAbnormalCount()+1);
                            d.setLackCount(1);
                            if (d.getAdjustName().equals("核算中")){
                                d.setAdjustName("缺卡1次");
                            }else {
                                d.setAdjustName(d.getAdjustName()+",缺卡"+d.getLackCount()+"次");
                            }
                        }
                    }
                    if (d.getAbnormalCount()==0){
                        d.setAdjustName("正常");
                    }
                    OaHumanClockCountBo bean = BeanUtil.toBean(d, OaHumanClockCountBo.class);
                    iOaHumanClockCountService.updateByBo(bean);
                }
            });
        }
    }

    /**
     * 定时任务把临时定时任务更改至定时任务库
     */

    @Scheduled(cron = "0 0 3 * * ?")
//    @Scheduled(cron = "0/20 * * * * ?")
    public void updateTempClockRule(){
        List<OaHumanClockTemp> oaHumanClockTemps = oaHumanClockTempMapper.selectList();
        if (CollectionUtil.isNotEmpty(oaHumanClockTemps)){
            oaHumanClockTemps.forEach(d->{
                OaHumanClock bean = BeanUtil.toBean(d, OaHumanClock.class);
                baseMapper.updateById(bean);
                oaHumanClockTempMapper.deleteById(d.getId());
            });
        }
    }


    /**
     * 定时非节假日将打卡记录进行处理、如果打了一次卡，添加一条方便管理员校准，如果没打卡，添加两条。
     */
    @Scheduled(cron = "0 0 1 * * ?")
//    @Scheduled(cron = "0/20 * * * * ?")
    public void DailyHandleCLockList(){
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Calendar calendar = Calendar.getInstance();
        // 将日期减去一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        // 将Calendar对象转换为Date对象
        Date yesterday = calendar.getTime();
        String yesterdayString = dateFormatIn.format(yesterday);
        List<OaHumanClockCountVo> lastCountList = iOaHumanClockCountService.selectCountByDate(yesterdayString);
        lastCountList.forEach(d->{
            if (d.getAdjustName().equals("正常(休息)")){

            }else {
                String clockListInfo = d.getClockList();
                JSONArray clockList = JSON.parseArray(clockListInfo);
                if (CollectionUtil.isEmpty(clockList)){
                    clockList=new JSONArray();
                }
                final Date[] date = {new Date(),new Date()};
                OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(d.getRuleId());
                //处理打卡时间逻辑
                String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
                JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
                clockTimeList.forEach( clockTime -> {
                    JSONObject m1 = (JSONObject) clockTime;
                    List list = (List) m1.get("checkedWeeks");
                    Calendar instance = Calendar.getInstance();
                    //获取昨天是星期几
                    int i = (instance.get(Calendar.DAY_OF_WEEK) -1 + 6) % 7;
                    if (list.indexOf(i) != -1){
                        //拿到打卡时间
                        JSONObject timeArray = (JSONObject) m1.get("timeArray");
                        String startTimeInfo = timeArray.getString("startTime");
                        String endTimeInfo = timeArray.getString("endTime");
                        try {
                            date[0] = sdf.parse(startTimeInfo);
                            date[1] = sdf.parse(endTimeInfo);
                        } catch (ParseException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
                if (CollectionUtil.isEmpty(clockList)){
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("type","上班");
                    jsonObject.put("status","缺卡");
                    jsonObject.put("standard",sdf.format(date[0]));
                    jsonObject.put("id", UUIdUtils.generateCustomId());
                    JSONObject jsonObject2 = new JSONObject();
                    jsonObject2.put("id", UUIdUtils.generateCustomId());
                    jsonObject2.put("type","下班");
                    jsonObject2.put("status","缺卡");
                    jsonObject2.put("standard",sdf.format(date[1]));
                    clockList.add(jsonObject);
                    clockList.add(jsonObject2);
                    d.setStartStatus("缺卡("+sdf.format(date[0])+")");
                    d.setEndStatus("缺卡("+sdf.format(date[1])+")");
                }else if (clockList.size()==1){
                    JSONObject jsonObject2 = new JSONObject();
                    jsonObject2.put("type","下班");
                    jsonObject2.put("id", UUIdUtils.generateCustomId());
                    jsonObject2.put("status","缺卡");
                    jsonObject2.put("standard",sdf.format(date[1]));
                    clockList.add(jsonObject2);
                    d.setEndStatus("缺卡("+sdf.format(date[1])+")");
                }else if (clockList.size()==2){
                    return;
                }
                d.setClockList(clockList.toString());
                OaHumanClockCountBo bean = BeanUtil.toBean(d, OaHumanClockCountBo.class);
                iOaHumanClockCountService.updateByBo(bean);
            }
        });
    }


    /**
     * 早上发送消息提醒
     */
    @Scheduled(cron = "0 20 8 * * ?")
//    @Scheduled(cron = "0/20 * * * * ?")
    public void sendMessageperDayOnWork(){
        SimpleDateFormat holidayFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date now = new Date();
        String dateString = holidayFormat.format(now);
        OaHoliday oaHoliday = iOaHolidayService.selectIsHoliday(dateString);
        if (ObjectUtil.isEmpty(oaHoliday)) {
            SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
            List<OaHumanClock> all = getAll();
            String minPattern = "HH:mm";
            SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
            for (OaHumanClock oaHumanClock : all) {
                //打卡人员：分别处理部门和人员
                String clockTypeList = oaHumanClock.getClockTypeList();
                JSONArray array = JSON.parseArray(clockTypeList);
                List<ClockUserDto> userList = new ArrayList<>();
                List<String> deptList = new ArrayList<>();
                String selectWhiteList = oaHumanClock.getSelectWhiteList();
                List<ClockUserDto> finalUserList = userList;
                array.forEach(d->{
                    JSONObject d1 = (JSONObject) d;
                    if (ObjectUtil.isNotNull(d1.get("label"))){
                        deptList.add(d1.get("id").toString());
                    }else {
                        ClockUserDto clockUserDto = new ClockUserDto();
                        clockUserDto.setUserId(d1.get("userId").toString());
                        clockUserDto.setNickName(d1.get("nickName").toString());
                        clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                        JSONObject dept = (JSONObject) d1.get("dept");
                        clockUserDto.setDeptName(dept.getString("deptName"));
                        finalUserList.add(clockUserDto);
                    }
                });
                if (CollectionUtil.isNotEmpty(deptList)){
                    String join = String.join(",", deptList);
                    List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
                    finalUserList.addAll(list);
                }
                Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
                userList=new ArrayList<>(distinctSet);
                //过滤白名单
                JSONArray whiteList = JSON.parseArray(selectWhiteList);
                List<String> whiteUserIdList = whiteList.stream().map(white -> {
                    JSONObject white1 = (JSONObject) white;
                    return white1.get("userId").toString();
                }).collect(Collectors.toList());
                userList= userList.stream().filter(white-> whiteUserIdList.indexOf(white.getUserId())==-1).collect(Collectors.toList());
                String format = dateFormatIn.format(now);
                userList.forEach(d->{
                    OaHumanClockCountVo oaHumanClockVos =iOaHumanClockCountService.selectLastByUserId(d.getUserId(),format);
                    if (oaHumanClockVos!=null){
                            if (oaHumanClockVos.getStartTime() == null) {
                                OaMessageBo oaMessageBo = new OaMessageBo();
                                oaMessageBo.setSendId(1L);
                                oaMessageBo.setRecordId(Long.valueOf(oaHumanClockVos.getUserId()));
                                oaMessageBo.setStatus(0);
                                oaMessageBo.setType(1);
                                oaMessageBo.setMessageContent("上班未打卡，请前往小程序进行打卡");
                                oaMessageBo.setTitle("上班打卡");
                                oaMessageBo.setCreateBy("admin");
                                oaMessageBo.setUpdateBy("admin");
                                Boolean aBoolean = iOaMessageService.insertByBo(oaMessageBo);
                                WeChatUtil wxService = new WeChatUtil();
                                String accessToken = wxService.getAccess_token();
                                if (StringUtils.isNotBlank(accessToken)) {
                                    String userOpenId = iSysUserService.getUserOpenId(oaHumanClockVos.getUserId());
                                    if (StringUtils.isNotBlank(userOpenId)) {
                                    OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(oaHumanClockVos.getRuleId());
                                    String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
                                    JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
                                    clockTimeList.forEach(m -> {
                                        JSONObject m1 = (JSONObject) m;
                                        List list = (List) m1.get("checkedWeeks");
                                        Calendar instance = Calendar.getInstance();
                                        int i = (instance.get(Calendar.DAY_OF_WEEK) + 6) % 7;
                                        if (list.indexOf(i) != -1) {
                                            //拿到打卡时间
                                            JSONObject timeArray = (JSONObject) m1.get("timeArray");
                                            //上下班打卡时段
                                            JSONArray periodList = timeArray.getJSONArray("periodList");
                                            String startTimeInfo = timeArray.getString("startTime");
                                            String values2[] = {oaHumanClockVos.getUserName(), "未打卡", "上班打卡", startTimeInfo, format};
                                            wxService.pushOneUser(wxService.getAccess_token()
                                                , userOpenId, "3",
                                                "nmDVqrlgLKmwRJMiKeLrriOgMFNAPTxEgqf-DkBEfJg"
                                                , values2);
                                        }
                                    });
                                }
                            }
                        }
                    }
                });
            }
        }
    }

    /**
     * 晚上发送消息提醒
     * @param vo
     */
    @Scheduled(cron = "0 30 17 * * ?")
//    @Scheduled(cron = "0/20 * * * * ?")
    public void sendMessageperDayOnOff(){
        SimpleDateFormat holidayFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date now = new Date();
        String dateString = holidayFormat.format(now);
        OaHoliday oaHoliday = iOaHolidayService.selectIsHoliday(dateString);
        if (ObjectUtil.isEmpty(oaHoliday)) {
            SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
            List<OaHumanClock> all = getAll();
            String minPattern = "HH:mm";
            SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
            for (OaHumanClock oaHumanClock : all) {
                //打卡人员：分别处理部门和人员
                String clockTypeList = oaHumanClock.getClockTypeList();
                JSONArray array = JSON.parseArray(clockTypeList);
                List<ClockUserDto> userList = new ArrayList<>();
                List<String> deptList = new ArrayList<>();
                String selectWhiteList = oaHumanClock.getSelectWhiteList();
                List<ClockUserDto> finalUserList = userList;
                array.forEach(d->{
                    JSONObject d1 = (JSONObject) d;
                    if (ObjectUtil.isNotNull(d1.get("label"))){
                        deptList.add(d1.get("id").toString());
                    }else {
                        ClockUserDto clockUserDto = new ClockUserDto();
                        clockUserDto.setUserId(d1.get("userId").toString());
                        clockUserDto.setNickName(d1.get("nickName").toString());
                        clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                        JSONObject dept = (JSONObject) d1.get("dept");
                        clockUserDto.setDeptName(dept.getString("deptName"));
                        finalUserList.add(clockUserDto);
                    }
                });
                if (CollectionUtil.isNotEmpty(deptList)){
                    String join = String.join(",", deptList);
                    List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
                    finalUserList.addAll(list);
                }
                Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
                userList=new ArrayList<>(distinctSet);
                //过滤白名单
                JSONArray whiteList = JSON.parseArray(selectWhiteList);
                List<String> whiteUserIdList = whiteList.stream().map(white -> {
                    JSONObject white1 = (JSONObject) white;
                    return white1.get("userId").toString();
                }).collect(Collectors.toList());
                userList= userList.stream().filter(white-> whiteUserIdList.indexOf(white.getUserId())==-1).collect(Collectors.toList());
                String format = dateFormatIn.format(now);
                userList.forEach(d->{
                    OaHumanClockCountVo oaHumanClockVos =iOaHumanClockCountService.selectLastByUserId(d.getUserId(),format);
                    if (oaHumanClockVos!=null){
                        if (oaHumanClockVos.getEndTime() == null) {
                            OaMessageBo oaMessageBo = new OaMessageBo();
                            oaMessageBo.setSendId(1L);
                            oaMessageBo.setRecordId(Long.valueOf(oaHumanClockVos.getUserId()));
                            oaMessageBo.setStatus(0);
                            oaMessageBo.setType(1);
                            oaMessageBo.setMessageContent("下班未打卡，请前往小程序进行打卡");
                            oaMessageBo.setTitle("下班打卡");
                            oaMessageBo.setCreateBy("admin");
                            oaMessageBo.setUpdateBy("admin");
                            Boolean aBoolean = iOaMessageService.insertByBo(oaMessageBo);
                            String userOpenId = iSysUserService.getUserOpenId(oaHumanClockVos.getUserId());
                            if (StringUtils.isNotBlank(userOpenId)) {
                                WeChatUtil wxService = new WeChatUtil();
                                String accessToken = wxService.getAccess_token();
                                if (StringUtils.isNotBlank(accessToken)) {
                                    OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(oaHumanClockVos.getRuleId());
                                    String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
                                    JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
                                    clockTimeList.forEach(m -> {
                                        JSONObject m1 = (JSONObject) m;
                                        List list = (List) m1.get("checkedWeeks");
                                        Calendar instance = Calendar.getInstance();
                                        int i = (instance.get(Calendar.DAY_OF_WEEK) + 6) % 7;
                                        if (list.indexOf(i) != -1) {
                                            //拿到打卡时间
                                            JSONObject timeArray = (JSONObject) m1.get("timeArray");
                                            //上下班打卡时段
                                            String endTimeInfo = timeArray.getString("endTime");
                                            String values2[] = {oaHumanClockVos.getUserName(), "未打卡", "下班打卡", endTimeInfo, format};

                                            wxService.pushOneUser(wxService.getAccess_token()
                                                , userOpenId, "3",
                                                "nmDVqrlgLKmwRJMiKeLrriOgMFNAPTxEgqf-DkBEfJg"
                                                , values2);
                                        }
                                    });
                                }
                             }
                        }
                    }
                });
            }
        }
    }

    //每年凌晨零点零分执行一次
    @Scheduled(cron = "0 0 0 1 1 ? ")
//@Scheduled(cron = "0/20 * * * * ?")
    public void collectData() throws ParseException {
        Calendar now = Calendar.getInstance();
        int i = now.get(Calendar.YEAR);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, Object> map = DateUtils.addHolidayAndWeekends(i + "");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            OaHolidayBo oaHoliday = new OaHolidayBo();
            String key = entry.getKey();
            Date date = dateFormat.parse(key);
            Map<String, Object> mapValue = (Map<String, Object>) entry.getValue();
            String name = mapValue.get("name").toString();
            String type = mapValue.get("type").toString();
            oaHoliday.setHolidayDate(date);
            oaHoliday.setName(name);
            oaHoliday.setType(type);
            iOaHolidayService.insertByBo(oaHoliday);
        }
    }


    @Override
    public void sysLeave(OaHumanLeaveVo vo) {

        LocalDate localDate1 = vo.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate localDate2 = vo.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        List<Date> dateList = Stream.iterate(localDate1, date -> date.plusDays(1))
            .limit(localDate1.until(localDate2).getDays() + 1)
            .map(date -> Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
            .collect(Collectors.toList());
        //拿到用户昨天的打卡记录
        List<OaHumanClock> all = getAll();
        String minPattern = "HH:mm";
        SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
        for (OaHumanClock oaHumanClock : all) {
            //打卡人员：分别处理部门和人员
            String clockTypeList = oaHumanClock.getClockTypeList();
            JSONArray array = JSON.parseArray(clockTypeList);
            List<ClockUserDto> userList = new ArrayList<>();
            List<String> deptList = new ArrayList<>();
            String selectWhiteList = oaHumanClock.getSelectWhiteList();
            List<ClockUserDto> finalUserList = userList;
            array.forEach(d -> {
                JSONObject d1 = (JSONObject) d;
                if (ObjectUtil.isNotNull(d1.get("label"))) {
                    deptList.add(d1.get("id").toString());
                } else {
                    ClockUserDto clockUserDto = new ClockUserDto();
                    clockUserDto.setUserId(d1.get("userId").toString());
                    clockUserDto.setNickName(d1.get("nickName").toString());
                    clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                    JSONObject dept = (JSONObject) d1.get("dept");
                    clockUserDto.setDeptName(dept.getString("deptName"));
                    finalUserList.add(clockUserDto);
                }
            });
            if (CollectionUtil.isNotEmpty(deptList)) {
                String join = String.join(",", deptList);
                List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
                finalUserList.addAll(list);
            }
            Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
            userList=new ArrayList<>(distinctSet);
            //过滤白名单
            JSONArray whiteList = JSON.parseArray(selectWhiteList);
            List<String> whiteUserIdList = whiteList.stream().map(white -> {
                JSONObject white1 = (JSONObject) white;
                return white1.get("userId").toString();
            }).collect(Collectors.toList());
            userList = userList.stream().filter(white -> whiteUserIdList.indexOf(white.getUserId()) == -1).collect(Collectors.toList());
            userList = userList.stream().filter(d -> d.getUserId().equals(vo.getUserId().toString())).collect(Collectors.toList());
            List<ClockUserDto> finalUserList1 = userList;
            if (CollectionUtil.isNotEmpty(finalUserList1)){
                dateList.forEach(d -> {
                    SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
                    String format = dateFormatIn.format(d);
                    //根据年月日、判断用户是否有打卡记录
                    OaHumanClockCountVo lastCount = iOaHumanClockCountService.selectLastByUserId(finalUserList1.get(0).getUserId(), format);
                    if (ObjectUtil.isEmpty(lastCount)) {
                        OaHumanClockCountBo count = new OaHumanClockCountBo();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd EEEE");
                        // 格式化日期并输出
                        String formattedDate = sdf.format(d);
                        formattedDate = formattedDate.replace("EEEE", "星期");
                        count.setClockDate(formattedDate);
                        count.setUserId(finalUserList1.get(0).getUserId());
                        count.setUserName(finalUserList1.get(0).getNickName());
                        count.setDeptName(finalUserList1.get(0).getDeptName());
                        count.setRoleName(finalUserList1.get(0).getRoleName());
                        count.setRuleId(oaHumanClock.getId());
                        count.setRuleName(oaHumanClock.getRuleName());
                        count.setClockShift(vo.getLeaveType());
                        count.setAdjustName("正常(休息)");
                        count.setClockCount(0);
                        String selectOutsideList = oaHumanClock.getSelectOutsideList();
                        if (StringUtils.isNotBlank(selectOutsideList)){
                            JSONArray outsideList = JSON.parseArray(selectOutsideList);
                            List<String> outsideListList = outsideList.stream().map(white -> {
                                JSONObject white1 = (JSONObject) white;
                                return white1.get("userId").toString();
                            }).collect(Collectors.toList());
                            if (outsideListList.indexOf(finalUserList1.get(0).getUserId()) != -1) {
                                count.setIsOutside(true);
                            } else {
                                count.setIsOutside(false);
                            }
                        }
                        iOaHumanClockCountService.insertByBo(count);
                    }
                });
            }

        }
    }


    @Override
    public void sysTrip(OaFinanceTripApplyVo vo){
        LocalDate localDate1 = vo.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate localDate2 = vo.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        List<Date> dateList = Stream.iterate(localDate1, date -> date.plusDays(1))
            .limit(localDate1.until(localDate2).getDays() + 1)
            .map(date -> Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
            .collect(Collectors.toList());
        //拿到用户昨天的打卡记录
//        OaHumanClockCountVo oaHumanClockCountVo = iOaHumanClockCountService.selectLastVoByUserId(vo.getUserId()+"");
        List<OaHumanClock> all = getAll();
        String minPattern = "HH:mm";
        SimpleDateFormat dateFormat = new SimpleDateFormat(minPattern);
        for (OaHumanClock oaHumanClock : all) {
            //打卡人员：分别处理部门和人员
            String clockTypeList = oaHumanClock.getClockTypeList();
            JSONArray array = JSON.parseArray(clockTypeList);
            List<ClockUserDto> userList = new ArrayList<>();
            List<String> deptList = new ArrayList<>();
            String selectWhiteList = oaHumanClock.getSelectWhiteList();
            List<ClockUserDto> finalUserList = userList;
            array.forEach(d->{
                JSONObject d1 = (JSONObject) d;
                if (ObjectUtil.isNotNull(d1.get("label"))){
                    deptList.add(d1.get("id").toString());
                }else {
                    ClockUserDto clockUserDto = new ClockUserDto();
                    clockUserDto.setUserId(d1.get("userId").toString());
                    clockUserDto.setNickName(d1.get("nickName").toString());
                    clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                    JSONObject dept = (JSONObject) d1.get("dept");
                    clockUserDto.setDeptName(dept.getString("deptName"));
                    finalUserList.add(clockUserDto);
                }
            });
            if (CollectionUtil.isNotEmpty(deptList)){
                String join = String.join(",", deptList);
                List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
                finalUserList.addAll(list);
            }
            Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
            userList=new ArrayList<>(distinctSet);
            //过滤白名单
            JSONArray whiteList = JSON.parseArray(selectWhiteList);
            List<String> whiteUserIdList = whiteList.stream().map(white -> {
                JSONObject white1 = (JSONObject) white;
                return white1.get("userId").toString();
            }).collect(Collectors.toList());
            userList= userList.stream().filter(white-> whiteUserIdList.indexOf(white.getUserId())==-1).collect(Collectors.toList());
            userList= userList.stream().filter(d -> d.getUserId().equals(vo.getUserId().toString())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(userList)){
                List<ClockUserDto> finalUserList1 = userList;
                dateList.forEach(d->{
                    SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
                    String format = dateFormatIn.format(d);
                    //根据年月日、判断用户是否有打卡记录
                    OaHumanClockCountVo lastCount = iOaHumanClockCountService.selectLastByUserId(finalUserList1.get(0).getUserId(), format);
                    if (ObjectUtil.isEmpty(lastCount)){
                        OaHumanClockCountBo count = new OaHumanClockCountBo();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd EEEE");
                        // 格式化日期并输出
                        String formattedDate = sdf.format(d);
                        formattedDate = formattedDate.replace("EEEE", "星期");
                        count.setClockDate(formattedDate);
                        count.setUserId(finalUserList1.get(0).getUserId());
                        count.setUserName(finalUserList1.get(0).getNickName());
                        count.setDeptName(finalUserList1.get(0).getDeptName());
                        count.setRoleName(finalUserList1.get(0).getRoleName());
                        count.setRuleId(oaHumanClock.getId());
                        count.setRuleName(oaHumanClock.getRuleName());
                        SimpleDateFormat holidayFormat = new SimpleDateFormat("yyyy-MM-dd");
                        String dateString = holidayFormat.format(d);
                        OaHoliday oaHoliday = iOaHolidayService.selectIsHoliday(dateString);
                        if (ObjectUtil.isEmpty(oaHoliday)) {
                            String clockTimeListInfo = oaHumanClock.getClockTimeList();
                            JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
                            clockTimeList.forEach(m -> {
                                JSONObject m1 = (JSONObject) m;
                                List list = (List) m1.get("checkedWeeks");
                                Calendar instance = Calendar.getInstance();
                                int i = (instance.get(Calendar.DAY_OF_WEEK) + 6) % 7;
                                if (list.indexOf(i) != -1) {
                                    JSONObject timeArray = (JSONObject) m1.get("timeArray");
//                                count.setClockShift(timeArray.get("startTime") + "-" + timeArray.get("endTime"));
                                    try {
                                        Date startTime = dateFormat.parse(timeArray.get("startTime").toString());
                                        Date endTime = dateFormat.parse(timeArray.get("endTime").toString());
                                        long minPoor = DateUtils.getMinPoor(endTime, startTime);
                                        //是否开启休息时间
                                        if ((Boolean) m1.get("enableRest")) {
                                            JSONObject restTime = (JSONObject) m1.get("restTime");
                                            Date startTime1 = dateFormat.parse(restTime.getString("startTime"));
                                            Date endTime1 = dateFormat.parse(restTime.getString("endTime"));
                                            count.setClockShift(timeArray.get("startTime") + "-"+restTime.getString("startTime")+"、"+restTime.getString("endTime")+"-" + timeArray.get("endTime"));
                                            long minPoor1 = DateUtils.getMinPoor(endTime1, startTime1);
                                            long minutes = minPoor - minPoor1;
                                            double hours = minutes / 60.0;
                                            DecimalFormat df = new DecimalFormat("#.0");
                                            String formattedHours = df.format(hours);
                                            count.setStandardWorkHour(Double.valueOf(formattedHours));
                                        } else {
                                            count.setClockShift(timeArray.get("startTime") + "-" + timeArray.get("endTime"));
                                            double hours = minPoor / 60.0;
                                            DecimalFormat df = new DecimalFormat("#.0");
                                            String formattedHours = df.format(hours);
                                            count.setStandardWorkHour(Double.valueOf(formattedHours));
                                        }
                                    } catch (ParseException e) {
                                        throw new RuntimeException(e);
                                    }
                                    count.setAdjustName("核算中");
                                }
                            });
                        }else {
                            count.setClockShift("休息");
                            count.setAdjustName("正常(休息)");
                        }
                        count.setClockCount(0);
                        count.setIsOutside(true);
                        iOaHumanClockCountService.insertByBo(count);
                    }
                });
            }
        }
    }

    /**
     * 根据用户id和当天时间
     * @param userId
     * @param date
     * @return
     */
    @Override
    public R<Boolean> getClockLocation(String userId, Date date,double longitude,double latitude){
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        String format = dateFormatIn.format(date);
        OaHumanClockCountVo oaHumanClockCountVo = iOaHumanClockCountService.selectLastByUserId(userId, format);
        if (oaHumanClockCountVo==null){
            return R.ok("当前用户无需打卡");
        }
        OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(oaHumanClockCountVo.getRuleId());
        String clockLocationListInfo = oaHumanClockVo.getClockLocationList();
        Double range=0.00;
        JSONArray clockLocationList = JSON.parseArray(clockLocationListInfo);
        for (Object clockLocationInfo : clockLocationList) {
            JSONObject clockLocation = (JSONObject) clockLocationInfo;
            double clockLongitude = clockLocation.getDouble("longitude");
            double clockLatitude = clockLocation.getDouble("latitude");
            range=0.00;
            double distance = DistanceUtils.calculateDistance(clockLatitude, clockLongitude, latitude, longitude);
            if (distance>clockLocation.getDouble("range")){
                range=distance;
            }else {
                range=0.00;
                break;
            }
        }
        if (range>0.00){
            return R.ok(false);
        }
        return R.ok(true);
    }

    /**
     * 跟据月份返回当前月用户打卡信息
     */
    public JSONArray getAllDatesInMonth(String yearMonth,String userId){
        JSONArray objects = new JSONArray();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        List<LocalDate> dates = new ArrayList<>();
        LocalDate startDate = LocalDate.parse(yearMonth + "-01");
        LocalDate endDate = startDate.plusMonths(1).minusDays(1);
        while (!startDate.isAfter(endDate)) {
            dates.add(startDate);
            startDate = startDate.plusDays(1);
        }
        dates.forEach(d->{
            String formattedDate = d.format(formatter2);
            OaHumanClockCountVo oaHumanClockCountVo = iOaHumanClockCountService.selectLastByUserId(userId, formattedDate);
            if (oaHumanClockCountVo!=null){
                if (!oaHumanClockCountVo.getAdjustName().equals("正常(休息)")){
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("date",d);
                    if (oaHumanClockCountVo.getAbnormalCount()!=0){
                        jsonObject.put("staus","异常");
                    }else {
                        jsonObject.put("staus","正常");
                    }
                    objects.add(jsonObject);
                }
            }
        });
        return objects;
    }

    @Override
    public int getAllShouldClockNum(){
        OaHumanClock oaHumanClock = baseMapper.selectOne(new LambdaQueryWrapper<>());
        if (oaHumanClock==null){
            return 0;
        }
        String clockTypeList = oaHumanClock.getClockTypeList();
        JSONArray array = JSON.parseArray(clockTypeList);
        List<ClockUserDto> userList = new ArrayList<>();
        List<String> deptList = new ArrayList<>();
        String selectWhiteList = oaHumanClock.getSelectWhiteList();
        List<ClockUserDto> finalUserList = userList;
        array.forEach(d->{
            JSONObject d1 = (JSONObject) d;
            if (ObjectUtil.isNotNull(d1.get("label"))){
                deptList.add(d1.get("id").toString());
            }else {
                ClockUserDto clockUserDto = new ClockUserDto();
                clockUserDto.setUserId(d1.get("userId").toString());
                clockUserDto.setNickName(d1.get("nickName").toString());
                clockUserDto.setRoleName(iSysDeptService.selectUserRolesByUserId(d1.get("userId").toString()));
                JSONObject dept = (JSONObject) d1.get("dept");
                clockUserDto.setDeptName(dept.getString("deptName"));
                finalUserList.add(clockUserDto);
            }
        });
        if (CollectionUtil.isNotEmpty(deptList)){
            String join = String.join(",", deptList);
            List<ClockUserDto> list = iSysDeptService.selectSonDateByIds(join);
            finalUserList.addAll(list);
        }
        Set<ClockUserDto> distinctSet = new HashSet<>(finalUserList);
        userList=new ArrayList<>(distinctSet);
        //过滤白名单
        JSONArray whiteList = JSON.parseArray(selectWhiteList);
        if (CollectionUtil.isNotEmpty(whiteList)){
            List<String> whiteUserIdList = whiteList.stream().map(white -> {
                JSONObject white1 = (JSONObject) white;
                return white1.get("userId").toString();
            }).collect(Collectors.toList());
            userList= userList.stream().filter(white-> whiteUserIdList.indexOf(white.getUserId())==-1).collect(Collectors.toList());
        }
        return userList.size();
    }

    /**
     * 按照月份统计所有考勤正常的人数
     * @param month
     * @return
     */
    @Override
    public Map<String, Object> SelectNormalUserByMonth(String month) {
        return iOaHumanClockCountService.SelectNormalUserByMonth(month);
    }

    /**
     * 根据用户时间判断当前打卡状态
     * @param clockDate
     * @param userId
     * @return
     */
    @Override
    public String getWorkOrOffClock(Date clockDate,String userId){
        AtomicReference<String> returnStatus= new AtomicReference<>("");
        Date now = new Date();
        SimpleDateFormat dateFormatIn = new SimpleDateFormat("yyyy/MM/dd");
        String format = dateFormatIn.format(now);
        //
        OaHumanClockCountVo oaHumanClockCountVo =iOaHumanClockCountService.selectLastByUserId(userId,format);
        if (oaHumanClockCountVo!=null){
            OaHumanClockVo oaHumanClockVo = baseMapper.selectVoById(oaHumanClockCountVo.getRuleId());
            //分钟转化
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            //处理打卡时间逻辑
            String clockTimeListInfo = oaHumanClockVo.getClockTimeList();
            JSONArray clockTimeList = JSON.parseArray(clockTimeListInfo);
            clockTimeList.forEach(d -> {
                JSONObject m1 = (JSONObject) d;
                List list = (List) m1.get("checkedWeeks");
                Calendar instance = Calendar.getInstance();
                int i = (instance.get(Calendar.DAY_OF_WEEK) + 6) % 7;
                Integer def;
                if (list.indexOf(i) != -1) {
                    //拿到打卡时间
                    JSONObject timeArray = (JSONObject) m1.get("timeArray");
                    //上下班打卡时段
                    JSONArray periodList = timeArray.getJSONArray("periodList");
                    String startTimeInfo = timeArray.getString("startTime");
                    String endTimeInfo = timeArray.getString("endTime");
                    try {
                        Date startTime = sdf.parse(startTimeInfo);
                        Date endTime = sdf.parse(endTimeInfo);
                        JSONObject startClock = (JSONObject) periodList.get(0);
                        JSONObject endClock = (JSONObject) periodList.get(1);
                        String offStartInfo = endClock.getString("startTime");
                        Date offStart = sdf.parse(offStartInfo);
                        String offEndInfo = endClock.getString("endTime");
                        Date offEnd = sdf.parse(offEndInfo);
                        String workStartInfo = startClock.getString("startTime");
                        Date workStart = sdf.parse(workStartInfo);
                        String workEndInfo = startClock.getString("endTime");
                        Date workEnd = sdf.parse(workEndInfo);
                        if (ObjectUtil.isEmpty(oaHumanClockCountVo.getStartTime()) && clockDate.getTime() <= workEnd.getTime()) {
                            returnStatus.set("上班打卡");
                        }else if (clockDate.getTime() > offStart.getTime() && clockDate.getTime() < offEnd.getTime()){
                            returnStatus.set("下班打卡");
                        }else {
                            returnStatus.set("不在打卡时间内");
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
        return returnStatus.get();
    }

    @Override
    public Map<String, Object> SelectNormalUserByDate(String date) {
        return iOaHumanClockCountService.SelectNormalUserByDate(date);
    }
}
